const TASK_STATUS = {
    PROCESSING: 1,
    SUCCESS: 2,
    ERROR: 3
}

class FileUploader {
    constructor({ element, uploadURL, taskRenderer }) {
        if (element instanceof HTMLElement) {
            this.element = element
        } else {
            throw new Error('element is not an HTMLElement')
        }
        this.uploadURL = uploadURL
        if (typeof taskRenderer === 'function') {
            this.taskRenderer = taskRenderer
        } else {
            throw new Error('taskRenderer is not a function')
        }
        this.#init()
    }

    // props
    tasks = []

    // private methods
    #init = () => {
        const dropAreaDOM = this.element.querySelector('.drop-area')
        // 鼠标在拖放目标上释放时触发
        dropAreaDOM.addEventListener('drop', this.#handleDrop)
        // 拖拽时鼠标在目标元素上移动时触发
        dropAreaDOM.addEventListener('dragover', this.#handleDragOver)
    }

    #handleDrop = (e) => {
        // 防止文件上传后自动打开
        e.preventDefault();
        // DataTransfer 对象用于保存拖动并放下过程中的数据
        if (e.dataTransfer.items) {
            // 包含所有拖动数据列表的 DataTransferItemList 对象
            for (const item of e.dataTransfer.items) {
                if (item.kind === 'file') {
                    const file = item.getAsFile()
                    console.log('file:', file);
                    this.#upload(file)
                }
            }
        } else {
            // 包含数据传输中可用的所有本地文件的列表
            for (const file of e.dataTransfer.files) {
                console.log('file:', file);
                this.#upload(file)
            }
        }
    }

    #handleDragOver = (e) => {
        e.preventDefault();
    }

    #upload = (file) => {
        const data = new FormData()
        data.append('file', file)
        const task = {
            id: this.tasks.length,
            name: file.name,
            status: TASK_STATUS.PROCESSING,
            progress: 0
        }
        this.tasks.unshift(task)

        const xhr = new XMLHttpRequest()
        xhr.open('POST', this.uploadURL)
        xhr.setRequestHeader('x-file-name', encodeURIComponent(file.name))
        xhr.upload.addEventListener('progress', (e) => {
            console.log('processing', e);
            const { loaded, total } = e
            const progress = Math.round(loaded / total * 100)
            task.progress = progress
            this.#updateTask(task)
        })
        xhr.addEventListener('load', () => {
            console.log('success');
            task.status = TASK_STATUS.SUCCESS
            const response = JSON.parse(xhr.response)
            const { url } = response
            task.url = url
            this.#updateTask(task)
        })
        xhr.addEventListener('error', () => {
            console.log('error');
            task.status = TASK_STATUS.ERROR
            this.#updateTask(task)
        })
        xhr.send(data)
    }

    #updateTask = (task) => {
        console.log('task', task);
        const taskList = this.element.querySelector('.task-list')
        const id = `task-${task.id}`
        let taskBox = taskList.querySelector(`#${id}`)
        if (!taskBox) {
            taskBox = document.createElement('div')
            taskBox.id = id
            taskList.prepend(taskBox)
        }
        taskBox.innerHTML = ''
        taskBox.append(this.taskRenderer(task))
    }
}